package com.jzit168.module_camera

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.os.Environment
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.VideoCapture
import androidx.camera.view.CameraView
import androidx.core.view.isVisible
import androidx.lifecycle.liveData
import com.alibaba.android.arouter.facade.annotation.Route
import com.jzit168.library_arouter.ARouterConstant
import com.jzit168.library_base.baseVB.BaseVBActivity
import com.jzit168.library_base.ext.requestPermission
import com.jzit168.library_base.ext.toast
import com.jzit168.library_utils.LogUtil
import com.jzit168.module_camera.databinding.ActivityCamera1Binding
import java.io.File
import java.util.concurrent.Executors
import kotlin.time.*

@ExperimentalTime
@Route(path = ARouterConstant.Camera.toCameraActivity1)
class Camera1Activity : BaseVBActivity<ActivityCamera1Binding>() {

    private val executor by lazy { Executors.newSingleThreadExecutor() }

    private val permissions by lazy {
        mutableListOf(
            Manifest.permission.CAMERA,
            Manifest.permission.RECORD_AUDIO
        )
    }

    private lateinit var photoFile: File

    private lateinit var videoFile: File

    override fun getViewBinding(): ActivityCamera1Binding =
        ActivityCamera1Binding.inflate(layoutInflater)

    @SuppressLint("MissingPermission")
    override fun initView(savedInstanceState: Bundle?) {
        super.initView(savedInstanceState)
        requestPermission(
            permissions,
            "需要开启相机权限才能正常拍照",
            "未开启相机权限,请在应用权限管理里开启相机权限"
        ) { allGranted, _, _ ->
            if (allGranted) {
                photoFile = getOutputDirectory(this)
                videoFile = getOutputVideoDir(this)
                binding.cameraView.bindToLifecycle(this)
                binding.radioPicture.isChecked = true
                binding.cameraView.captureMode = CameraView.CaptureMode.IMAGE
            } else {
                finish()
            }
        }
    }

    private var isStart = false

    override fun initListener() {
        super.initListener()
        binding.apply {
            group.setOnCheckedChangeListener { group, checkedId ->
                when (checkedId) {
                    radioPicture.id -> {
                        cameraView.captureMode = CameraView.CaptureMode.IMAGE
                        takePicture.setImageResource(R.drawable.drawable_take_stated)
                        binding.videoTime.isVisible = false
                    }
                    radioVideo.id -> {
                        cameraView.captureMode = CameraView.CaptureMode.VIDEO
                        takePicture.setImageResource(R.drawable.drawable_video_normal)
                    }
                }
            }
            takePicture.setOnClickListener {
                try {
                    when (cameraView.captureMode) {
                        CameraView.CaptureMode.IMAGE -> {
                            takePicture()
                        }
                        CameraView.CaptureMode.VIDEO -> {
                            if (isStart) {
                                isStart = false
                                stopVideo()
                                binding.takePicture.setImageResource(R.drawable.drawable_video_normal)
                            } else {
                                isStart = true
                                binding.takePicture.setImageResource(R.drawable.drawable_video_stop)
                                takeVideo()
                            }
                        }
                        else -> {

                        }
                    }
                } catch (e: Exception) {
                    LogUtil.e(e)
                }
            }
        }
    }

    private fun takePicture() {
        val photoFile = createFile(photoFile, "image_${System.currentTimeMillis()}", ".jpg")

        val metadata = ImageCapture.Metadata()

        val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile)
            .setMetadata(metadata)
            .build()

        binding.apply {
            videoTime.isVisible = false
            cameraView.takePicture(
                outputOptions,
                executor, object : ImageCapture.OnImageSavedCallback {
                    override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
                        val saveUri = outputFileResults.savedUri ?: Uri.fromFile(photoFile)
                        LogUtil.e(saveUri)
                    }

                    override fun onError(exception: ImageCaptureException) {
                        LogUtil.e(exception)
                    }
                })

        }
    }

    @SuppressLint("RestrictedApi")
    private fun takeVideo() {
        binding.videoTime.isVisible = true
        val videoFile = createFile(videoFile, "video_${System.currentTimeMillis()}", ".mp4")
        val metadata = VideoCapture.Metadata()

        val outputOptions = VideoCapture.OutputFileOptions.Builder(videoFile)
            .setMetadata(metadata)
            .build()
        binding.cameraView.startRecording(
            outputOptions,
            executor,
            object : VideoCapture.OnVideoSavedCallback {
                override fun onVideoSaved(outputFileResults: VideoCapture.OutputFileResults) {
                    val saveUri = outputFileResults.savedUri ?: Uri.fromFile(videoFile)
                    LogUtil.e(saveUri)
                }

                override fun onError(videoCaptureError: Int, message: String, cause: Throwable?) {
                    LogUtil.e("$videoCaptureError---$message---$cause")
                }
            })

    }

    private fun stopVideo() =
        if (binding.cameraView.isRecording) binding.cameraView.stopRecording() else toast("暂未录制")

    private var start = 0

    private fun sendTime(isRecord: Boolean) {
        val flow = liveData {
            while (isRecord) {
                start++
                kotlinx.coroutines.delay(1000)
                emit(start)
            }
        }
        if (isRecord) {
            flow.observe(this, {
                LogUtil.e(it)
            })
        } else {
            flow.removeObservers(this)
        }
    }

    private fun createFile(
        outputFile: File,
        filename: String,
        photoExtension: String
    ) =
        File(outputFile, "$filename$photoExtension")


    private fun getOutputDirectory(context: Context): File {
        val dir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
        return if (dir != null && dir.exists()) {
            dir
        } else {
            context.applicationContext.filesDir
        }
    }

    private fun getOutputVideoDir(context: Context): File {
        val dir = context.getExternalFilesDir(Environment.DIRECTORY_DCIM)
        return if (dir != null && dir.exists()) {
            dir
        } else {
            context.applicationContext.filesDir
        }
    }

}